package com.storlead.security.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.storlead.security.model.RespBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * @Author: timo
 * @Date: 2019/3/20 19:37
 * @Description: Security 配置中心
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 授权
     */
    @Autowired
    CustomMetadataSource metadataSource;
    /**
     * 认证
     */
    @Autowired
    UrlAccessDecisionManager urlAccessDecisionManager;
    /**
     * 没有权限
     */
    @Autowired
    MyAuthenticationAccessDeniedHandler deniedHandler;
    /**
     * 登陆失败返回的json
     */
    @Autowired
    MyAuthenticationFailHandler myAuthenticationFailHandler;
    /**
     * 登陆成功之后返回的json
     */
    @Autowired
    MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    /**
     * 登出json
     */
    @Autowired
    MyLogoutSuccessHandler myLogoutSuccessHandler;


    /**
     * 登陆密码验证
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 认证管理器，这里后期配置成数据查询的
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        String password = new BCryptPasswordEncoder().encode("123");
        auth.inMemoryAuthentication().withUser("admin").password(password).roles("ADMIN");
        auth.inMemoryAuthentication().withUser("timo").password(password).roles("USER");
        auth.inMemoryAuthentication().withUser("1").password(password).roles("ALL");
        auth.inMemoryAuthentication().withUser("2").password(password).roles("TEST");
    }

    /**
     * 以下的静态资源不拦截
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/index.html", "/static/**", "/login_p", "/favicon.ico");
    }

    /**
     * Security 配置
     * 1.注入拦截器
     * 2.登陆
     * 3.登出
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(metadataSource);
                        o.setAccessDecisionManager(urlAccessDecisionManager);
                        return o;
                    }
                })
                .and()
                .formLogin()
                    .loginPage("/to_login").permitAll()// 这里不知道为什么一定是要/login_p 不是这个还报错了
                    .loginProcessingUrl("/login").permitAll()
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .failureHandler(myAuthenticationFailHandler)
                    .successHandler(myAuthenticationSuccessHandler)
                    .permitAll()
                .and()
                    .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessHandler(myLogoutSuccessHandler)
                    .permitAll()
                .and().csrf().disable()
                .exceptionHandling().accessDeniedHandler(deniedHandler);
    }
}